package main;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import utils.DataManipulation;
import weka.classifiers.Classifier;
import weka.core.Instances;
import bagging.Bagging;

public class MainBagging {
	
	public static void main (String ...args){
		
		// argumentos
		// baseClassifier weka.classifiers.trees.J48 options -C 0.25 -M 2 dataset /home/andreybicalho/java_workspace/TP2_MachineLearning/iris.arff bagsize 15 NbaseClassifiers 5 trainSplit 60 iteracoes 5
	    Vector classifierOptions = new Vector();
	    String classifier = "";
	    String dataset_path = "";
	    
	    int bagSizeSplit = 10;
	    int numberBaseClassifiers = 3;
	    double percentSplit = 70;
	    int iteracoes = 1;
	    
		int i = 0;
		String current = "";
		boolean newPart = false; 
		do {
			// determine part of command line
			if (args[i].equals("baseClassifier")) {
				current = args[i];
				i++;
				newPart = true;
			} else if (args[i].equals("options")) {
				current = args[i];
				i++;
				newPart = true;
			} else if (args[i].equals("dataset")) {
				current = args[i];
				i++;
				newPart = true;
			} else if(args[i].equals("bagsize")) {
				current = args[i];
				i++;
				newPart = true;
			} else if(args[i].equals("NbaseClassifiers")) {
				current = args[i];
				i++;
				newPart = true;
			} else if(args[i].equals("trainSplit")) {
				current = args[i];
				i++;
				newPart = true;
			}
			else if(args[i].equals("iteracoes")) {
				current = args[i];
				i++;
				newPart = true;
			}

			
			
			
			if (current.equals("baseClassifier")) {
				if (newPart)
					classifier = args[i];
				else
					classifierOptions.add(args[i]);
			}
			else if(current.equals("options")){
					classifierOptions.add(args[i]);
			}
			else if (current.equals("dataset")) {
				if (newPart)
					dataset_path = args[i];
			}
			else if (current.equals("bagsize")) {
				if(newPart)
					bagSizeSplit = Integer.parseInt(args[i]);
			}
			else if (current.equals("NbaseClassifiers")) {
				if(newPart)
					numberBaseClassifiers = Integer.parseInt(args[i]);
			}
			else if (current.equals("trainSplit")) {
				if(newPart)
					percentSplit = Integer.parseInt(args[i]);
			}
			else if (current.equals("iteracoes")) {
				if(newPart)
					iteracoes = Integer.parseInt(args[i]);
			}

			// next parameter
			i++;
			newPart = false;
		} while (i < args.length);
	    		
		String[] options = (String[])classifierOptions.toArray(new String[classifierOptions.size()]); 
//		System.out.println(options.length);
//		for (int j = 0; j < options.length; j++) {
//			System.out.println(options[j]);
//		}
//		exemplo de argumentos:
//		baseClassifier weka.classifiers.trees.J48 options -C 0.25 -M 2 dataset /home/andreybicalho/java_workspace/TP2_MachineLearning/iris.arff bagsize 15 NbaseClassifiers 5 trainSplit 60
		
		
		List<Double> acuracia = new ArrayList<Double>();
		
		//load data
		DataManipulation dataManipulation = new DataManipulation(dataset_path,"arff");
		
		int trainSize = (int)(dataManipulation.getDataset().numInstances() * percentSplit / 100);
        int testSize = dataManipulation.getDataset().numInstances() - trainSize;
        Instances trainSet = new Instances(dataManipulation.getDataset(), 0, trainSize);
        
        //Instances testSet = new Instances(dataManipulation.getDataset(), trainSize, dataManipulation.getDataset().numInstances());        
		
		// bagging process
		for (int n = 0; n < iteracoes; n++) {
			Bagging bagging = null;
			try {
				bagging = new Bagging(trainSet, Classifier.forName(classifier,
						options), numberBaseClassifiers, dataManipulation
						.getDataset().numClasses());
			} catch (Exception e) {
				// TODO: handle exception
				System.out.println("Error while creating bagging classifier");
				e.printStackTrace();
			}
			// build bagging meta-classifier
			// System.out.println("Bag size Split: " + bagSizeSplit +
			// "   Number of base Classifiers: " + numberBaseClassifiers +
			// "   Train split: " + percentSplit);
			bagging.buildBagging(bagSizeSplit);

			// int classificador1 = 0,classificador2 = 1, classificador3 = 2;

			// System.out.println("initializing training....");

			// classifica conjunto de treino
			int numCorrect = 0;
			// int numCorrect1 = 0, numCorrect2 = 0, numCorrect3 = 0;
			// for (int j = 0; j < trainSet.numInstances(); j++) {
			//
			// double pred = bagging.classifyInstance(trainSet.instance(j));
			// if (pred == trainSet.instance(j).classValue())
			// numCorrect++;
			//
			//			
			// try{
			// double pred1 =
			// bagging.getBaseClassifiers()[classificador1].classifyInstance(trainSet.instance(j));
			// if (pred1 == trainSet.instance(j).classValue())
			// numCorrect1++;
			//			
			// double pred2 =
			// bagging.getBaseClassifiers()[classificador2].classifyInstance(trainSet.instance(j));
			// if(pred2 == trainSet.instance(j).classValue())
			// numCorrect2++;
			//			
			// double pred3 =
			// bagging.getBaseClassifiers()[classificador3].classifyInstance(trainSet.instance(j));
			// if(pred3 == trainSet.instance(j).classValue())
			// numCorrect3++;
			//			
			// }catch(Exception e){
			//				
			// }
			//			
			// }
			//		
			// System.out.println("Classificador1: " + numCorrect1 + " de " +
			// trainSize + " foram classificadas corretamente. ("
			// + ((double) numCorrect1 / (double)trainSize * 100) + "%)");
			//		
			// System.out.println("Classificador2: " + numCorrect2 + " de " +
			// trainSize + " foram classificadas corretamente. ("
			// + ((double) numCorrect2 / (double)trainSize * 100) + "%)");
			//		
			// System.out.println("Classificador3: " + numCorrect3 + " de " +
			// trainSize + " foram classificadas corretamente. ("
			// + ((double) numCorrect3 / (double)trainSize * 100) + "%)");
			//		
			// System.out.println("Bagging no Treino: " + numCorrect + " de " +
			// trainSize + " foram classificadas corretamente. ("
			// + ((double) numCorrect / (double)trainSize * 100) + "%)");

			// System.out.println("initializing testing....");
			// classifica conjunto de test
			numCorrect = 0;
			// numCorrect1 = 0; numCorrect2 = 0; numCorrect3 = 0;
			for (int j = trainSize; j < dataManipulation.getDataset()
					.numInstances(); j++) {

				double pred = bagging.classifyInstance(dataManipulation
						.getDataset().instance(j));
				if (pred == dataManipulation.getDataset().instance(j)
						.classValue())
					numCorrect++;

				// try{
				// double pred1 =
				// bagging.getBaseClassifiers()[classificador1].classifyInstance(dataManipulation.getDataset().instance(j));
				// if (pred1 ==
				// dataManipulation.getDataset().instance(j).classValue())
				// numCorrect1++;
				//				
				// double pred2 =
				// bagging.getBaseClassifiers()[classificador2].classifyInstance(dataManipulation.getDataset().instance(j));
				// if(pred2 ==
				// dataManipulation.getDataset().instance(j).classValue())
				// numCorrect2++;
				//				
				// double pred3 =
				// bagging.getBaseClassifiers()[classificador3].classifyInstance(dataManipulation.getDataset().instance(j));
				// if(pred3 ==
				// dataManipulation.getDataset().instance(j).classValue())
				// numCorrect3++;
				//				
				// }catch(Exception e){}

			}
			acuracia.add((double) numCorrect / (double) testSize * 100);
			// salva
			Double media = new Double(dataManipulation.getMean(acuracia));
			Double stdDev = new Double(dataManipulation.getStdDev(acuracia));
			String pathFile = "meta_" + classifier + "_bagging.txt";
			dataManipulation.save_to_file(media, stdDev, pathFile);
			
			// System.out.println("Classificador1: " + numCorrect1 + " de " +
			// testSize + " foram classificadas corretamente. ("
			// + ((double) numCorrect1 / (double)testSize * 100) + "%)");
			//			
			// System.out.println("Classificador2: " + numCorrect2 + " de " +
			// testSize + " foram classificadas corretamente. ("
			// + ((double) numCorrect2 / (double)testSize * 100) + "%)");
			//			
			// System.out.println("Classificador3: " + numCorrect3 + " de " +
			// testSize + " foram classificadas corretamente. ("
			// + ((double) numCorrect3 / (double)testSize * 100) + "%)");

			// System.out.println("Bagging no teste: " + numCorrect + " de " +
			// testSize + " foram classificadas corretamente. ("
			// + ((double) numCorrect / (double)testSize * 100) + "%)");

			// System.out.println(((double) numCorrect / (double)testSize * 100)
			// + "%");

		}
	}

}
